﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Natural.Helpers;
using Natural.Model;
using Natural.Providers;

namespace Natural.Managers
{

    public class Implementation
    {
        private static object syncRoot = new Object();
        private static ImplementationInfo info;
        public static ImplementationInfo Info
        {
            get
            {
                if (info == null)
                {
                    lock (syncRoot)
                    {
                        if (info == null)
                        {
                            info = new ImplementationInfo();
                            Load(info);
                        }
                    }
                }
                return info;

            }
        }

        private static void Load(ImplementationInfo info)
        {
            info.Assemblies = new List<Assembly>();
            info.Providers = new List<Type>();
            info.Entities = new List<Type>();
            info.Actions = new List<Type>();            
            info.Decorators = new List<Type>();
            info.Observers = new List<Type>(); 

            info.Assemblies = new List<Assembly>();
            foreach (FileInfo p in new DirectoryInfo(Environment.CurrentDirectory).GetFiles("*.dll"))
            {
                try
                {
                    info.Assemblies.Add(Assembly.Load(Path.GetFileNameWithoutExtension(p.Name)));
                }
                catch (Exception exception)
                {
                    Logger.Log(exception);
                }
            }
            Attributes.Entity entity = new Attributes.Entity();            
            foreach (Assembly assembly in info.Assemblies)
            {
                foreach (Type p in assembly.GetTypes().Where(p => p.IsClass && p.IsPublic && !p.IsAbstract))
                {
                    if (ReflectionHelper.Contain(p, entity))
                    {
                        Info.Entities.Add(p);
                    }
                    else
                    {
                        Attributes.Impl att = ReflectionHelper.Attribute<Attributes.Impl>(p);
                        if (att != null)
                        {
                            switch (att.Type)
                            {
                                case Attributes.ImplType.Provider: Info.Providers.Add(p); break;
                                case Attributes.ImplType.Action: Info.Actions.Add(p); break;
                                case Attributes.ImplType.Decorator: Info.Decorators.Add(p); break;
                                case Attributes.ImplType.Observer: Info.Observers.Add(p); break;
                            }
                        }
                    }
                }
            }
        }
    }
}
